#ifndef DATAFLOW_H
#define DATAFLOW_H


#include <string>
#include <memory>
//#include <list>

//using std::list;
using std::auto_ptr;

using std::string;

class U_Ptr
{
	friend class DataFlow;
	size_t Use;
	U_Ptr() : Use(1) {}
	~U_Ptr() {}
};

class DataFlow
{
public:
	DataFlow(): BufferLength(0), Buffer(0), PtrCount(new U_Ptr) { }//printf("~~~~new make %d~~~~", ++i); }
    DataFlow(const string s) : PtrCount(new U_Ptr)
    {
        SetData(s.c_str(), s.length() + 1);
    }
    DataFlow(const char* s) : PtrCount(new U_Ptr)
    {
        SetData(s, s ? strlen(s) + 1 : 0);
    }
    DataFlow(const long int n) : PtrCount(new U_Ptr)
    {
        SetData((char *)&n, sizeof(long int));
    }
    DataFlow(const void* buffer, unsigned int length) : PtrCount(new U_Ptr)
    {
        SetData((char *)buffer, length);
    }
    DataFlow(const DataFlow &orig) : PtrCount(orig.PtrCount)
    {
		BufferLength = orig.BufferLength;
		Buffer = orig.Buffer;
		PtrCount->Use++;
    }
	DataFlow & operator += ( int i )
	{
		int c;
		if ( !GetNumber(c) ) return *this;		
		if ( GetLength() < sizeof(int) ) return *this;
		c += i;
		memcpy( GetData(), &c, sizeof(int) );
		return *this;
	}
    DataFlow & operator = ( const DataFlow &rhs )
    {
		++rhs.PtrCount->Use;
		ClearBuffer();
		BufferLength = rhs.BufferLength;
		Buffer = rhs.Buffer;
		PtrCount = rhs.PtrCount;
        return *this;
    }
    ~DataFlow()
    {
		ClearBuffer();
    }
	char* ReSet(unsigned int length)
    {
		ClearBuffer();
		//printf("~~~~new make %d~~~~", ++i);
		PtrCount = new U_Ptr;
        if (length > 0)
        {
            BufferLength = length;
            Buffer = new char[length];
        }
		else 
		{
			BufferLength = 0;
			Buffer = 0;
		}
		return Buffer;
    }
	size_t CopyData(void *dest, size_t size) const
	{
		if(Buffer) 
		{
			memcpy(dest, Buffer, size > BufferLength ? BufferLength : size);
			return size > BufferLength ? BufferLength : size;
		}
		else return 0;
	}
    char * GetData() const
    {
        return Buffer;
    }
	char * GetListData(int num, int size) const
	{
		if ( (size * num >= BufferLength) ||
			(!Buffer) ) return NULL;
		return Buffer + size * num;
	}
	int GetListNumber(int size) const
	{
		if (BufferLength % size != 0) return -1;
		return BufferLength / size;
	}
	template <typename T>
	bool GetNumber(T &n)
	{
		long int i = 0;
		if (!BufferLength) return 0;
		memcpy(&i, Buffer, BufferLength);
		n = i;
		return 1;
	}
	bool GetNumber(long int *i)
	{
		if (!BufferLength) return 0;
		memcpy(i, Buffer, BufferLength);
		return 1;
	}
    unsigned int GetLength() const
    {
        return BufferLength;
    }

private:
    void ClearBuffer()
    {
		if (--PtrCount->Use == 0)
		{
		//	printf("~~~~old clear %d~~~~", --i);
			delete PtrCount;
			if (Buffer) delete [] Buffer;
		}
    }
	void SetData(const char* buffer, unsigned int length)
    {
		//printf("~~~~new make %d~~~~", ++i);
        if ((buffer) && (length > 0))
        {
            BufferLength = length;
            Buffer = new char[length];
            memcpy(Buffer, buffer, BufferLength);
        }
		else 
		{
			BufferLength = 0;
			Buffer = 0;
		}
    }
    //bool changed;
	static int i;
    unsigned int BufferLength;
    char *Buffer;
	U_Ptr *PtrCount;
};

















#endif